/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ua.yandex.collections;

public class MyArrayList implements MyList {

    private static final  int defaultCapasity = 10;
    private static final  int ratio = 3;
    private Object[] list;
    private int capacity;
    private int length;

    public MyArrayList() {
        capacity = defaultCapasity;
        list = new Object[capacity];
        length = 0;
    }

    public MyArrayList(int initialCapacity) {
        capacity = initialCapacity;
        list = new Object[capacity];
        length = 0;
    }

    public void ensureCapacity(int minCapacity) {
        if (capacity < minCapacity) {
            Object[] newList = new Object[minCapacity];
            System.arraycopy(list, 0, newList, 0, length);
            list = newList;
            capacity = minCapacity;
        }
    }

    @Override
    public Object remove(int index) {
        Object o = get(index);
        if ((capacity > 2 * defaultCapasity) && ((length - 1)
                < (capacity / ratio))) {

            Object[] newList = new Object[capacity / 2];
            if (index > 0) {
                System.arraycopy(list, 0, newList, 0, index);
            }

            System.arraycopy(list, index + 1, newList, index,
                    length - index - 1);
            list = newList;
            capacity = capacity / 2;
        } else {
            System.arraycopy(list, index + 1, list, index, length - 1 - index);

        }
        length -= 1;
        return o;
    }

    @Override
    public void add(Object e) {
        if (length == capacity) {
            ensureCapacity(2 * capacity);

        }
        list[length] = e;
        length += 1;
    }

    @Override
    public void add(int index, Object e) {
        if ((index > length) || (index < 0)) {
            throw new OutOfRangeException();
        } else {
            if (length == capacity) {
                ensureCapacity(2 * capacity);
            }
            System.arraycopy(list, index, list, index + 1, length - index);
            list[index] = e;
            length += 1;
        }
    }

    @Override
    public void addAll(Object[] c) {
        addAll(length, c);
    }

    @Override
    public void addAll(int index, Object[] c) {
        if ((c == null) || (c.length == 0)) {
            return;
        }
        if ((index > length) || (index < 0)) {
            throw new OutOfRangeException("fail");
        } else {

            if ((length + c.length) > capacity) {
                ensureCapacity(Math.max(2 * capacity, length + c.length));
            }
            System.arraycopy(list, index, list, index + c.length,
                    length - index);
            System.arraycopy(c, 0, list, index, c.length);
            length += c.length;
        }
    }

    @Override
    public Object get(int index) {
        if ((index > length - 1) || (index < 0)) {
            throw new OutOfRangeException();
        } else {
            return list[index];
        }
    }

    @Override
    public void set(int index, Object e) {
        if ((index > length - 1) || (index < 0)) {
            throw new OutOfRangeException();
        } else {
            list[index] = e;
        }
    }

    @Override
    public int indexOf(Object o) {
        for (int i = 0; i < length; i++) {
            if (list[i] == o) {
                return i;
            }
        }
        return -1;
    }

    @Override
    public int size() {
        return length;
    }

    @Override
    public void clear() {
        capacity = defaultCapasity;
        length = 0;
        list = new Object[capacity];
    }

    @Override
    public boolean isEmpty() {
        if (length == 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public Object[] toArray() {
        if (length == 0) {
            return null;
        } else {
            Object[] newList = new Object[length];
            System.arraycopy(list, 0, newList, 0, length);
            return newList;
        }
    }

    @Override
    public String toString() {
        String s = "";
        for (int i = 0; i < length; i++) {
            s = s.concat(list[i].toString());
        }
        return s;
    }

}
